// bslma_sequentialallocator.h                                        -*-C++-*-
#ifndef INCLUDED_BSLMA_SEQUENTIALALLOCATOR
#define INCLUDED_BSLMA_SEQUENTIALALLOCATOR

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Support fast memory allocation for objects of varying sizes.
//
//@DEPRECATED: Use `bdlma_bufferedsequentialallocator` instead.
//
//@CLASSES:
//  bslma::SequentialAllocator: fast variable-size memory allocator
//
//@SEE_ALSO: bdlma_sequentialallocator, bdlma_bufferedsequentialallocator
//
//@DESCRIPTION: This component provides an allocator,
// `bslma::SequentialAllocator`, that implements the `bslma::ManagedAllocator`
// protocol and allocates memory blocks of any requested size, from an internal
// buffer (pool) or a user-supplied buffer.  If an allocation request exceeds
// the remaining free memory space in the pool, the pool either 1) replenishes
// its buffer with new memory to satisfy the request, or 2) returns a separate
// memory block, depending on whether the request size exceeds an optionally
// specified maximum buffer size.  By default, buffer growth is not capped.
// The `release` method releases all memory allocated through this allocator,
// as does the destructor.  Note, however, that individual allocated blocks of
// memory cannot be separately deallocated.
// ```
//  ,--------------------------.
// ( bslma::SequentialAllocator )
//  `--------------------------'
//               |         ctor/dtor
//               |         allocateAndExpand
//               |         expand
//               |         reserveCapacity
//               |         truncate
//               V
//   ,-----------------------.
//  ( bslma::ManagedAllocator )
//   `-----------------------'
//               |        release
//               V
//      ,-----------------.
//     (  bslma::Allocator )
//      `-----------------'
//                      allocate
//                      deallocate
// ```
//
///Alignment Strategy
///------------------
// The `bslma::SequentialPool` allocates memory using one of the two alignment
// strategies (defined in `bslma_bufferallocator`) optionally specified at
// construction: 1) MAXIMUM ALIGNMENT or 2) NATURAL ALIGNMENT.
//
// 1. MAXIMUM ALIGNMENT: This strategy always allocates memory aligned with the
//    most restrictive alignment on the host platform.  The value is defined by
//    `bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT`.
// 2. NATURAL ALIGNMENT: This strategy allocates memory whose alignment depends
//    on the requested number of bytes.  An object of a fundamental type
//    (`int`, etc.) is *naturally* *aligned* when it's size evenly divides its
//    address.  An object of an aggregate type has natural alignment if the
//    alignment of the most-restrictively aligned sub-object evenly divides the
//    address of the aggregate.  Natural alignment is always at least as
//    restrictive as the compiler's required alignment.  When only the size of
//    an aggregate is known, and not its composition, we compute the alignment
//    by finding the largest integral power of 2 (up to and including
//    `bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT`) that divides the requested
//    (non-zero) number of bytes.  This computed alignment is guaranteed to be
//    at least as restrictive as any sub-object within the aggregate.
//
// The default strategy is NATURAL ALIGNMENT.
//
///Optional `buffer` Parameter
///---------------------------
// A buffer can be supplied to a `bslma::SequentialAllocator` object at
// construction in which case the allocator will try to satisfy allocation
// requests using this buffer before switching to a dynamically-allocated
// internal pool.  Once the allocator is using an internal pool, it will not
// try to satisfy any subsequent allocation requests from the supplied buffer.
// Note that the allocator does *not* take ownership of the buffer.  Also note
// that `bufferSize` may be specified using a positive or negative value to
// indicate a buffer growth strategy (see "Internal Buffer Growth").
//
///Optional `initialSize` Parameter
///--------------------------------
// In lieu of an externally-supplied buffer, a value for the `initialSize`
// parameter may be supplied at construction to specify the initial size of the
// internal pool.  If neither a buffer nor an `initialSize` is specified, an
// implementation-defined value is used for an initial size of the internal
// pool.  Note that `initialSize` may be specified using a positive or negative
// value to indicate a buffer growth strategy (see "Internal Buffer Growth").
//
///Internal Buffer Growth
///----------------------
// A `bslma::SequentialAllocator` replenishes its internal buffer if the
// current buffer cannot satisfy an allocation request.  It does so by one of
// two growth strategies:
//
//: Constant Growth: The new buffer is always of the same size as the current
//:   buffer (possibly supplied at construction).
//:
//: Geometric Growth: The new buffer will be geometrically larger than the
//:   current buffer up to an optionally-specified maximum limit.
//
// If a `bufferSize` (and corresponding `buffer`) or `initialSize` is supplied
// at construction, the sign of its value implicitly specifies which growth
// strategy to use.  A positive value indicates Constant Growth, whereas a a
// negative value indicates Geometric Growth.  If neither `bufferSize` nor
// `initialSize` is supplied, Geometric Growth is used.  The optional
// `maxBufferSize` parameter may be used to place a cap on Geometric Growth
// (`maxBufferSize` is ignored if Constant Growth is in effect).  If no value
// is specified for `maxBufferSize`, there is no cap on Geometric Growth.  Note
// that `reserveCapacity` always ensures that the requested number of bytes is
// available (allocating a new internal pool if necessary) irrespective of
// whether the size of the request exceeds `maxBufferSize`.
//
///Usage
///-----
// Allocators are often supplied to objects requiring dynamically-allocated
// memory at construction.  For example, consider the following
// `my_DoubleStack` class, parameterized by a `bslma::Allocator`:
// ```
// // my_doublestack.h
// // ...
//
// namespace bslma { class Allocator; }
//
// class my_DoubleStack {
//     // DATA
//     double           *d_stack_p;      // dynamically-allocated array
//     int               d_size;         // physical capacity this stack
//     int               d_length;       // next available index in stack
//     bslma::Allocator *d_allocator_p;  // memory allocator (held, not owned)
//
//     // FRIENDS
//     friend class my_DoubleStackIter;
//
//   private:
//     // PRIVATE MANIPULATORS
//     void increaseSize();
//         // Increase the capacity of this stack by at least one element.
//
//   public:
//     // CREATORS
//     my_DoubleStack(bslma::Allocator       *basicAllocator = 0);
//     my_DoubleStack(const my_DoubleStack&  original,
//                    bslma::Allocator       *basicAllocator = 0);
//     ~my_DoubleStack();
//
//     // MANIPULATORS
//     my_DoubleStack& operator=(const my_DoubleStack& rhs);
//     void push(double value);
//     void pop();
//
//     // ACCESSORS
//     const double& top() const;
//     bool isEmpty() const;
// };
//
// // ...
//
// // MANIPULATORS
// inline
// void my_DoubleStack::push(double value)
// {
//     if (d_length >= d_size) {
//         increaseSize();
//     }
//     d_stack_p[d_length++] = item;
// }
//
// // ...
// ```
// The stack interface takes an optional `basicAllocator` supplied only at
// construction.  (We avoid use of the name `allocator` so as not to conflict
// with the STL use of the word, which differs slightly.)  If non-zero, the
// stack holds a pointer to this allocator, but does not own it.  If no
// allocator is supplied, the implementation itself must either conditionally
// invoke global `new` and `delete` explicitly whenever dynamic memory must be
// managed (BAD IDEA) or (GOOD IDEA) install a default allocator that adapts
// use of these global operators to the `bslma_allocator` interface.  In actual
// practice, however, we might want the default to be run-time settable from a
// central location (see `bslma_default`).
// ```
// // my_doublestack.cpp
// // ...
// #include <my_doublestack.h>
// #include <bslma_allocator.h>
// #include <bslma_default.h>  // adapter for 'new' and 'delete'
//
// enum { INITIAL_SIZE = 1, GROW_FACTOR = 2 };
//
// // ...
//
// // CREATORS
// my_DoubleStack::my_DoubleStack(bslma::Allocator *basicAllocator)
// : d_size(INITIAL_SIZE)
// , d_length(0)
// , d_allocator_p(basicAllocator)
// {
//     assert(d_allocator_p);
//     d_stack_p = (double *)
//                 d_allocator_p->allocate(d_size * sizeof *d_stack_p);
// }
//
// my_DoubleStack::~my_DoubleStack()
// {
//     // CLASS INVARIANTS
//     assert(d_allocator_p);
//     assert(d_stack_p);
//     assert(0 <= d_length);
//     assert(0 <= d_size);
//     assert(d_length <= d_size);
//
//     d_allocator_p->deallocate(d_stack_p);
// }
// ```
// Even in this simplified implementation, all use of the allocator protocol is
// relegated to the `.cpp` file.  Subsequent use of the allocator is
// demonstrated by the following file-scope static reallocation function:
// ```
// static
// void reallocate(double **array, int newSize, int length,
//                 bslma::Allocator *basicAllocator)
//     // Reallocate memory in the specified 'array' to have the specified
//     // 'newSize' using the specified 'basicAllocator'.  The specified
//     // 'length' number of leading elements are preserved.  Given that the
//     // internal policy of class 'my_DoubleStack' requires that the physical
//     // capacity of the container may grow but never shrink, the behavior is
//     // undefined unless length <= newSize.
// {
//     assert(array);
//     assert(1 <= newSize);
//     assert(0 <= length);
//     assert(basicAllocator);
//     assert(length <= newSize);        // enforce class invariant
//
//     double *tmp = *array;             // support exception neutrality
//     *array = (double *) basicAllocator->allocate(newSize * sizeof **array);
//
//     // COMMIT POINT
//
//     std::memcpy(*array, tmp, length * sizeof **array);
//     basicAllocator->deallocate(tmp);
// }
//
// void my_DoubleStack::increaseSize()
// {
//     int proposedNewSize = d_size * GROW_FACTOR;     // reallocate can throw
//     assert(proposedNewSize > d_length);
//     reallocate(&d_stack_p, proposedNewSize, d_length, d_allocator_p);
//     d_size = proposedNewSize;                       // we're committed
// }
// ```

#ifdef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
#error "bslma_sequentialallocator is deprecated"
#endif
#include <bslscm_version.h>

#include <bslma_bufferallocator.h>
#include <bslma_managedallocator.h>
#include <bslma_sequentialpool.h>

#include <bsls_keyword.h>

namespace BloombergLP {


namespace bslma {

class Allocator;

                       // =========================
                       // class SequentialAllocator
                       // =========================

/// This class implements the `ManagedAllocator` protocol to provide a fast
/// allocator of arbitrarily-sized blocks of memory.  Both the `release`
/// method and the destructor atomically delete all memory managed by this
/// allocator; the `deallocate` method, however, has no effect for this
/// class.
class SequentialAllocator : public ManagedAllocator {

    // DATA
    SequentialPool d_sequentialPool;  // sequential pool mechanism

    // NOT IMPLEMENTED
    SequentialAllocator(const SequentialAllocator&);
    SequentialAllocator& operator=(const SequentialAllocator&);

  public:
    // CREATORS

    /// Create a sequential allocator for allocating memory blocks from an
    /// internal buffer.  Optionally specify an alignment `strategy` used to
    /// align allocated memory blocks.  If `strategy` is not specified,
    /// *Natural Alignment* is used.  Optionally specify an `initialSize`
    /// the absolute value of which indicates the initial size (in bytes)
    /// for the internal buffer.  If `initialSize` is not specified, an
    /// implementation-defined value is used.  Optionally specify a
    /// `basicAllocator` used to supply memory.  If `basicAllocator` is 0,
    /// the currently installed default allocator is used.  If an `allocate`
    /// or `reserveCapacity` request cannot be satisfied from the current
    /// buffer, a new buffer is allocated, the size of which is determined
    /// by a buffer growth strategy implied by `initialSize`.  If
    /// `initialSize` was specified and is negative, or if it was *not*
    /// specified, the buffer growth strategy used is *Geometric Growth*;
    /// otherwise it is *Constant Growth*.  (See the component level
    /// documentation for further details.)  In either case, the new buffer
    /// will have sufficient capacity to satisfy the request.  If *Geometric
    /// Growth* is in effect, no limit is imposed on the size of buffers.
    explicit SequentialAllocator(Allocator *basicAllocator = 0);
    explicit SequentialAllocator(
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);
    explicit SequentialAllocator(int        initialSize,
                                 Allocator *basicAllocator = 0);
    SequentialAllocator(
                       int                                 initialSize,
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);

    /// Create a sequential allocator for allocating memory blocks initially
    /// from the specified `buffer` the size (in bytes) of which is
    /// indicated by the absolute value of the specified `bufferSize`.
    /// Optionally specify an alignment `strategy` used to align allocated
    /// memory blocks.  If `strategy` is not specified, *Natural Alignment*
    /// is used.  Optionally specify a `basicAllocator` used to supply
    /// memory.  If `basicAllocator` is 0, the currently installed default
    /// allocator is used.  If an `allocate` or `reserveCapacity` request
    /// cannot be satisfied from the current buffer, a new buffer is
    /// allocated, the size of which is determined by a buffer growth
    /// strategy implied by `bufferSize`.  If `bufferSize` is negative, the
    /// buffer growth strategy used is *Geometric Growth*; otherwise it is
    /// *Constant Growth*.  (See the component level documentation for
    /// further details.)  In either case, the new buffer will have
    /// sufficient capacity to satisfy the request.  If *Geometric Growth*
    /// is in effect, no limit is imposed on the size of buffers.
    SequentialAllocator(char      *buffer,
                        int        bufferSize,
                        Allocator *basicAllocator = 0);
    SequentialAllocator(
                       char                               *buffer,
                       int                                 bufferSize,
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);

    /// Create a sequential allocator for allocating memory blocks from an
    /// internal buffer the initial size (in bytes) of which is indicated by
    /// the absolute value of the specified `initialSize`.  The specified
    /// `maxBufferSize` indicates the maximum size (in bytes) allowed for
    /// internally allocated buffers.  Optionally specify an alignment
    /// `strategy` used to align allocated memory blocks.  If `strategy` is
    /// not specified, *Natural Alignment* is used.  Optionally specify a
    /// `basicAllocator` used to supply memory.  If `basicAllocator` is 0,
    /// the currently installed default allocator is used.  If an `allocate`
    /// or `reserveCapacity` request cannot be satisfied from the current
    /// buffer, a new buffer is allocated, the size of which is determined
    /// by a buffer growth strategy implied by `initialSize`.  If
    /// `initialSize` is negative, the buffer growth strategy used is
    /// *Geometric Growth*; otherwise it is *Constant Growth*.  (See the
    /// component level documentation for further details.)  In either case,
    /// the new buffer will have sufficient capacity to satisfy the request.
    /// If *Geometric Growth* is in effect, the geometric progression of
    /// buffer sizes is capped at `maxBufferSize`.  The behavior is
    /// undefined unless `0 < maxBufferSize`, and
    /// `|initialSize| <= maxBufferSize`.  Note that `maxBufferSize` is
    /// ignored if `initialSize > 0`.  Also note that `maxBufferSize` may be
    /// overridden by a sufficiently large value passed to `allocate` or
    /// `reserveCapacity`.
    SequentialAllocator(int        initialSize,
                        int        maxBufferSize,
                        Allocator *basicAllocator = 0);
    SequentialAllocator(
                       int                                 initialSize,
                       int                                 maxBufferSize,
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);

    /// Create a sequential allocator for allocating memory blocks initially
    /// from the specified `buffer` the size (in bytes) of which is
    /// indicated by the absolute value of the specified `bufferSize`.  The
    /// specified `maxBufferSize` indicates the maximum size (in bytes)
    /// allowed for internally allocated buffers.  Optionally specify an
    /// alignment `strategy` used to align allocated memory blocks.  If
    /// `strategy` is not specified, *Natural Alignment* is used.
    /// Optionally specify a `basicAllocator` used to supply memory.  If
    /// `basicAllocator` is 0, the currently installed default allocator is
    /// used.  If an `allocate` or `reserveCapacity` request cannot be
    /// satisfied from the current buffer, a new buffer is allocated, the
    /// size of which is determined by a buffer growth strategy implied by
    /// `bufferSize`.  If `bufferSize` is negative, the buffer growth
    /// strategy used is *Geometric Growth*; otherwise it is *Constant
    /// Growth*.  (See the component level documentation for further
    /// details.)  In either case, the new buffer will have sufficient
    /// capacity to satisfy the request.  If *Geometric Growth* is in
    /// effect, the geometric progression of buffer sizes is capped at
    /// `maxBufferSize`.  The behavior is undefined unless
    /// `0 < maxBufferSize`, and `|bufferSize| <= maxBufferSize`.  Note that
    /// `maxBufferSize` is ignored if `bufferSize > 0`.  Also note that
    /// `maxBufferSize` may be overridden by a sufficiently large value
    /// passed to `allocate` or `reserveCapacity`.
    SequentialAllocator(char      *buffer,
                        int        bufferSize,
                        int        maxBufferSize,
                        Allocator *basicAllocator = 0);
    SequentialAllocator(
                       char                               *buffer,
                       int                                 bufferSize,
                       int                                 maxBufferSize,
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);

    /// Destroy this sequential allocator and release all associated memory.
    ~SequentialAllocator() BSLS_KEYWORD_OVERRIDE;

    // MANIPULATORS

    /// Return a newly allocated block of memory of (at least) the specified
    /// positive `size` (bytes).  If `size` is 0, a null pointer is returned
    /// with no effect.  The behavior is undefined unless `0 <= size`.  Note
    /// that the alignment of the address returned is the maximum alignment
    /// for any fundamental type defined for the calling platform.
    void *allocate(size_type numBytes) BSLS_KEYWORD_OVERRIDE;

    /// Return memory of at least the specified `*size` and return the
    /// actual amount of memory allocated in `*size`.  If `*size` is 0, no
    /// memory is allocated and 0 is returned.  The behavior is undefined
    /// unless `0 <= *size`.
    void *allocateAndExpand(int *size);

    /// Return memory of at least the specified `*size` and at most the
    /// specified `maxNumBytes`.  Also return the actual amount of memory
    /// allocated in `*size`.  If `*size` is 0, no memory is allocated and 0
    /// is returned.  The behavior is undefined unless
    /// `0 <= *size <= maxNumBytes`.
    void *allocateAndExpand(int *size, int maxNumBytes);

    /// This method has no effect for this allocator.
    void deallocate(void *address) BSLS_KEYWORD_OVERRIDE;

    /// Increase the amount of memory allocated at the specified `address`
    /// from the specified `originalNumBytes` to the maximum amount easily
    /// obtainable.  Return the amount of memory available at `address`
    /// after the expansion.  The behavior is undefined unless the call to
    /// this allocator that provided the `address` was performed with the
    /// `originalNumBytes`.  Note that this function will not expand the
    /// memory unless there have been no allocations since the allocation
    /// for `originalNumBytes`.
    int expand(void *address, int originalNumBytes);

    /// Increase the amount of memory allocated at the specified `address`
    /// from the specified `originalNumBytes` to the maximum amount easily
    /// obtainable up to the specified `maxNumBytes`.  Return the amount of
    /// memory available at `address` after the expansion.  The behavior is
    /// undefined unless the call to this allocator that provided the
    /// `address` was performed with the `originalNumBytes` and
    /// `originalNumBytes < maxNumBytes`.  Note that this function will not
    /// expand the memory unless there have been no allocations since the
    /// allocation for `originalNumBytes`.
    int expand(void *address, int originalNumBytes, int maxNumBytes);

    /// Release all memory currently allocated through this allocator.
    void release() BSLS_KEYWORD_OVERRIDE;

    /// Reserve sufficient memory to satisfy allocation requests for at
    /// least the specified `numBytes` without replenishment (i.e., without
    /// internal allocation).  The behavior is undefined unless
    /// `0 <= numBytes`.
    virtual void reserveCapacity(int numBytes);

    /// Reduce the amount of memory allocated at the specified `address`
    /// from the specified `originalNumBytes` to the specified
    /// `newNumBytes`.  Return the amount of memory available at `address`
    /// after the truncation.  The behavior is undefined unless the call to
    /// this allocator that provided the `address` was performed with the
    /// `originalNumBytes` and `newNumBytes <= originalNumBytes`.  Note that
    /// this function will not truncate the memory unless there have been no
    /// allocations since the allocation for `originalNumBytes`.
    int truncate(void *address, int originalNumBytes, int newNumBytes);
};

// ============================================================================
//                          INLINE DEFINITIONS
// ============================================================================

// CREATORS
inline
SequentialAllocator::SequentialAllocator(Allocator *basicAllocator)
: d_sequentialPool(basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(strategy, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(int        initialSize,
                                         Allocator *basicAllocator)
: d_sequentialPool(initialSize, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            int                                 initialSize,
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(initialSize, strategy, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(char      *buffer,
                                         int        bufferSize,
                                         Allocator *basicAllocator)
: d_sequentialPool(buffer, bufferSize, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            char                               *buffer,
                            int                                 bufferSize,
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(buffer, bufferSize, strategy, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(int        initialSize,
                                         int        maxBufferSize,
                                         Allocator *basicAllocator)
: d_sequentialPool(initialSize, maxBufferSize, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            int                                 initialSize,
                            int                                 maxBufferSize,
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(initialSize, maxBufferSize, strategy, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(char      *buffer,
                                         int        bufferSize,
                                         int        maxBufferSize,
                                         Allocator *basicAllocator)
: d_sequentialPool(buffer, bufferSize, maxBufferSize, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            char                               *buffer,
                            int                                 bufferSize,
                            int                                 maxBufferSize,
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(buffer, bufferSize, maxBufferSize, strategy, basicAllocator)
{
}

// MANIPULATORS
inline
void *SequentialAllocator::allocate(size_type numBytes)
{
    return d_sequentialPool.allocate(static_cast<int>(numBytes));
}

inline
void *SequentialAllocator::allocateAndExpand(int *size)
{
    return d_sequentialPool.allocateAndExpand(size);
}

inline
void *SequentialAllocator::allocateAndExpand(int *size, int maxNumBytes)
{
    return d_sequentialPool.allocateAndExpand(size, maxNumBytes);
}

inline
void SequentialAllocator::deallocate(void *)
{
}

inline
int SequentialAllocator::expand(void *address, int originalNumBytes)
{
    return d_sequentialPool.expand(address, originalNumBytes);
}

inline
int SequentialAllocator::expand(void *address,
                                int   originalNumBytes,
                                int   maxNumBytes)
{
    return d_sequentialPool.expand(address, originalNumBytes, maxNumBytes);
}

inline
void SequentialAllocator::release()
{
    d_sequentialPool.release();
}

inline
void SequentialAllocator::reserveCapacity(int numBytes)
{
    d_sequentialPool.reserveCapacity(numBytes);
}

inline
int SequentialAllocator::truncate(void *address,
                                  int   originalNumBytes,
                                  int   newNumBytes)
{
    return d_sequentialPool.truncate(address, originalNumBytes, newNumBytes);
}

}  // close package namespace

#ifndef BDE_OPENSOURCE_PUBLICATION  // BACKWARD_COMPATIBILITY
// ============================================================================
//                           BACKWARD COMPATIBILITY
// ============================================================================

/// This alias is defined for backward compatibility.
typedef bslma::SequentialAllocator bslma_SequentialAllocator;
#endif  // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY

}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2013 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
